using System;
using System.Windows;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace NLarge
{

    /// <summary>
    ///     SpotGrab can capture regions of the desktop
    ///     and find the color of the center pixel
    /// </summary>
    /// <remarks>
    ///     Alexander Lih May-June 2006
    ///     http://feebdack.com
    /// </remarks>

    class SpotGrab : INotifyPropertyChanged
    {
        protected int mPosX;
        protected int mPosY;
        protected int spotWidth;
        protected int spotHeight;

        protected int bumpX;
        protected int bumpY;
        protected int originX;
        protected int originY;

        protected System.Drawing.Point cursorPoint;
        protected BitmapSource curSpotBmpSrc;
        protected System.Windows.Media.Color curCursorColor;

        public SpotGrab(System.Drawing.Point curMousePos, int setupWidth, int setupHeight)
        {

            SpotWidth = setupWidth;
            SpotHeight = setupHeight;
            CursorPosition = curMousePos;
        }

        public System.Drawing.Point CursorPosition
        {
            get { return cursorPoint; }
            set
            {
                if (cursorPoint != value)
                {
                    cursorPoint = value;
                    mPosX = value.X;
                    mPosY = value.Y;
                    originX = value.X - bumpX;
                    originY = value.Y - bumpY;
                    SetSpotInfo();
                }
            }

        }

        public System.Drawing.Size SpotSize
        {
            get { return new System.Drawing.Size(SpotWidth, SpotHeight); }
            set
            {
                if (spotWidth != value.Width || spotHeight != value.Height)
                {
                    spotWidth = value.Width; spotHeight = value.Height;
                    bumpX = (int)((double)(value.Width) / 2);
                    bumpY = (int)((double)(value.Height) / 2);
                    originX = CursorPosition.X - bumpX;
                    originY = CursorPosition.Y - bumpY;
                    SetSpotInfo();
                }
            }
        }

        public void Capture()
        {
            SetSpotInfo();
        }

        public int SpotWidth
        {
            get { return spotWidth; }

            set
            {
                if (spotWidth != value)
                {
                    spotWidth = value;
                    bumpX = (int)((double)(value) / 2);
                    originX = CursorPosition.X - bumpX;
                    if (spotWidth > 0 && spotHeight > 0) SetSpotInfo();
                }
            }
        }

        public int SpotHeight
        {
            get { return spotHeight; }

            set
            {
                if (spotHeight != value)
                {
                    spotHeight = value;
                    bumpY = (int)((double)(value) / 2);
                    originY = CursorPosition.Y - bumpY;
                    if (spotWidth > 0 && spotHeight > 0) SetSpotInfo();
                }
            }
        }

        public BitmapSource CurrentSpotBmpSrc
        {
            get { return curSpotBmpSrc; }
            set
            {
                curSpotBmpSrc = value;
                OnPropertyChanged("CurrentSpotBmpSrc");
            }
        }

        public System.Windows.Media.Color CurrentCursorColor
        {
            get { return curCursorColor; }
            set
            {
                curCursorColor = value;
                OnPropertyChanged("CurrentCursorColor");
            }
        }

        #region ///Imported Screen Methods
        class ImportedMethods
        {

            [DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
            public static extern IntPtr DeleteDC(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
            public static extern IntPtr DeleteObject(IntPtr hDc);

            [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
            public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
            wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int RasterOp);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
            public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

            [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
            public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

            [DllImport("gdi32.dll", EntryPoint = "SelectObject")]
            public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
            [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
            public static extern IntPtr GetDesktopWindow();

            [DllImport("user32.dll", EntryPoint = "GetDC")]
            public static extern IntPtr GetDC(IntPtr ptr);

            [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
            public static extern int GetSystemMetrics(int abc);

            [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
            public static extern IntPtr GetWindowDC(IntPtr ptr);

            [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
            public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);

        }
        #endregion


        public void SetSpotInfo()
        {
            int x = originX;
            int y = originY;

            IntPtr hwnd = ImportedMethods.GetDesktopWindow();
            IntPtr dc = ImportedMethods.GetWindowDC(hwnd);
            IntPtr memDC = ImportedMethods.CreateCompatibleDC(dc);
            IntPtr hbm = ImportedMethods.CreateCompatibleBitmap(dc, spotWidth, spotHeight);
            IntPtr oldbm = ImportedMethods.SelectObject(memDC, hbm);
            bool b = ImportedMethods.BitBlt(
                    memDC,
                    0, 0,
                    SpotWidth, SpotHeight,
                    dc,
                    x, y,
                    0x40CC0020);

            // Make Cursor Color Brush
            System.Drawing.Bitmap tempBitmap = System.Drawing.Image.FromHbitmap(hbm);
            CurrentCursorColor = ConvertColor(tempBitmap.GetPixel(bumpX, bumpY));

            IntPtr tempHBitmap = tempBitmap.GetHbitmap();

            CurrentSpotBmpSrc = Imaging.CreateBitmapSourceFromHBitmap(
                tempHBitmap,
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            ImportedMethods.SelectObject(memDC, oldbm);
            ImportedMethods.DeleteObject(hbm);
            ImportedMethods.DeleteDC(memDC);
            ImportedMethods.ReleaseDC(hwnd, dc);

            ImportedMethods.DeleteObject(tempHBitmap);
            tempBitmap.Dispose();

        }

        public System.Windows.Media.Color ConvertColor(System.Drawing.Color col)
        {
            System.Windows.Media.Color resCol = new System.Windows.Media.Color();
            resCol.A = col.A;
            resCol.R = col.R;
            resCol.G = col.G;
            resCol.B = col.B;
            return resCol;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

    }
}
